﻿package baseEngine.modifiers
{
    import baseEngine.core.*;
    import com.gengine.global.*;
    import flash.events.*;
    import flash.geom.*;
    import flash.utils.*;
    import frEngine.*;
    import frEngine.animateControler.keyframe.*;
    import frEngine.event.*;
    import frEngine.math.*;
    import frEngine.pools.*;

    public class Modifier extends EventDispatcher implements IPoolObject
    {
        protected var _isPlaying:Boolean = false;
        protected var _defaultLable:Label3D;
        private var _currentDuring:int = 0;
        public var labels:Dictionary;
        private var _targetObject3d:Pivot3D;
        protected var _lastFrame:Number = -1;
        public var changeFrame:Boolean = false;
        private var frameCallbackMap:Dictionary;
        private var _scriptLen:uint = 0;
        public var curPlayTrackName:String;
        public var cuPlayLable:Label3D;
        public var autoPlay:Boolean = true;
        protected var _currentFrame:int;
        protected var _keyframes:Array;
        protected var _cache:Array;
        protected var _baseValue:Object;
        public var offsetFrame:int = 0;
        private var _user:Object;
        private var _isDisposed:Boolean = false;
        static const vectorX:Vector3D = new Vector3D();
        static const vectorY:Vector3D = new Vector3D();
        static const angleToPad:Number = 0.0174533;
        public static const maxFrame:uint = 300;

        public function Modifier()
        {
            this.labels = new Dictionary(false);
            this.frameCallbackMap = new Dictionary(false);
            this._keyframes = new Array();
            this._cache = new Array();
            return;
        }// end function

        public function get user() : Object
        {
            return this._user;
        }// end function

        public function set user(param1:Object) : void
        {
            this._user = param1;
            return;
        }// end function

        public function get defaultLable() : Label3D
        {
            var _loc_1:* = new Label3D(0, 0, "#default#", 0);
            this._defaultLable = new Label3D(0, 0, "#default#", 0);
            return this._defaultLable;
        }// end function

        public function set targetObject3d(param1:Pivot3D) : void
        {
            if (!param1 && this._targetObject3d)
            {
                this.setTargetProperty(this._baseValue);
            }
            if (param1 && !this.targetObject3d)
            {
                this._baseValue = this.getBaseValue(param1);
            }
            this._targetObject3d = param1;
            return;
        }// end function

        public function get type() : int
        {
            return AnimateControlerType.DefaultAnimateControler;
        }// end function

        public function get targetObject3d() : Pivot3D
        {
            return this._targetObject3d;
        }// end function

        public function clone() : Modifier
        {
            return this;
        }// end function

        public function get totalFrames() : int
        {
            return this.cuPlayLable ? (this.cuPlayLable.length) : (0);
        }// end function

        public function toUpdateAnimate(param1:Boolean = false) : void
        {
            if (this._isPlaying && this.cuPlayLable)
            {
                this.updateCurFrame();
            }
            else
            {
                this.changeFrame = false;
            }
            if (this._keyframes.length == 0 || !param1 && !this.changeFrame)
            {
                return;
            }
            if (this._cache[this.currentFrame] == null)
            {
                this.calculateFrameValue(this.currentFrame);
            }
            this.setTargetProperty(this._cache[this.currentFrame]);
            return;
        }// end function

        protected function calculateFrameValue(param1:int) : void
        {
            var _loc_5:Number = NaN;
            var _loc_6:NodeAnimateKey = null;
            var _loc_7:int = 0;
            var _loc_8:int = 0;
            var _loc_9:Boolean = false;
            var _loc_10:int = 0;
            var _loc_11:int = 0;
            var _loc_12:Number = NaN;
            var _loc_13:Number = NaN;
            var _loc_2:* = getTimeIndex(param1, this._keyframes);
            var _loc_3:* = this._keyframes[_loc_2];
            var _loc_4:* = _loc_3.value;
            if (_loc_3.frame == param1 || _loc_2 == (this._keyframes.length - 1))
            {
                this._cache[param1] = _loc_4 + this._baseValue;
            }
            else
            {
                _loc_6 = this._keyframes[(_loc_2 + 1)];
                _loc_7 = _loc_3.frame;
                _loc_8 = _loc_6.frame;
                _loc_9 = _loc_3.bezierVo.isLineTween || _loc_6.bezierVo.isLineTween;
                _loc_10 = param1 + 2 + int(Math.random() * 30);
                var _loc_14:* = _loc_8;
                _loc_10 = _loc_8;
                if (_loc_9)
                {
                    _loc_12 = _loc_3.value;
                    _loc_13 = (_loc_6.value - _loc_12) / (_loc_8 - _loc_7);
                    _loc_11 = param1;
                    while (_loc_11 < _loc_10)
                    {
                        
                        if (!this._cache[_loc_11])
                        {
                            this._cache[_loc_11] = _loc_12 + (_loc_11 - _loc_7) * _loc_13 + this._baseValue;
                        }
                        _loc_11++;
                    }
                }
                else
                {
                    NumberUtil.getBezierData(_loc_7, _loc_8, _loc_7 + _loc_3.bezierVo.RX, _loc_8 + _loc_6.bezierVo.LX, vectorX);
                    NumberUtil.getBezierData(_loc_3.value, _loc_6.value, _loc_3.value + _loc_3.bezierVo.RY, _loc_6.value + _loc_6.bezierVo.LY, vectorY);
                    _loc_11 = param1;
                    while (_loc_11 < _loc_10)
                    {
                        
                        if (!this._cache[_loc_11])
                        {
                            this._cache[_loc_11] = NumberUtil.getBezierTimeAndValue(_loc_11, vectorX, vectorY) + this._baseValue;
                        }
                        _loc_11++;
                    }
                }
            }
            return;
        }// end function

        protected function getBaseValue(param1:Pivot3D) : Object
        {
            return null;
        }// end function

        protected function setTargetProperty(param1) : void
        {
            return;
        }// end function

        public function removeLabel(param1:Label3D) : Label3D
        {
            var _loc_2:Pivot3D = null;
            delete this.labels[param1.trackName];
            return param1;
        }// end function

        public function getLabel(param1:String) : Label3D
        {
            return this.labels[param1];
        }// end function

        public function addLabel(param1:Label3D) : Label3D
        {
            if (this.labels[param1.trackName] != null)
            {
                return this.labels[param1.trackName];
            }
            this.labels[param1.trackName] = param1;
            if (this.curPlayTrackName == param1.trackName)
            {
                this.setPlayLable(this.curPlayTrackName);
            }
            return param1;
        }// end function

        public function setPlayLable(param1:Object, param2:Boolean = true) : Label3D
        {
            var _loc_3:Label3D = null;
            if (param1 is String)
            {
                _loc_3 = this.labels[param1];
                this.curPlayTrackName = String(param1);
            }
            else if (param1 is Label3D)
            {
                var _loc_4:* = param1;
                this.labels[param1.trackName] = param1;
                _loc_3 = _loc_4;
                this.curPlayTrackName = _loc_3.trackName;
            }
            if (!_loc_3)
            {
                return null;
            }
            this.cuPlayLable = _loc_3;
            this._lastFrame = 0;
            if (this.autoPlay)
            {
                this.play();
            }
            return _loc_3;
        }// end function

        final public function set currentFrame(param1:int) : void
        {
            var _loc_2:Dictionary = null;
            var _loc_3:int = 0;
            var _loc_4:int = 0;
            var _loc_5:Dictionary = null;
            var _loc_6:Function = null;
            var _loc_7:int = 0;
            var _loc_8:int = 0;
            if (param1 < 0)
            {
                param1 = 0;
            }
            if (param1 == this._currentFrame)
            {
                return;
            }
            this._currentFrame = param1;
            if (this._lastFrame != this._currentFrame)
            {
                _loc_2 = this._scriptLen > 0 ? (this.frameCallbackMap[this.curPlayTrackName]) : (null);
                if (_loc_2 != null && this.cuPlayLable)
                {
                    _loc_3 = this._currentFrame - this._lastFrame;
                    _loc_4 = this.cuPlayLable.length;
                    if (_loc_3 < 0 || this._currentFrame == (_loc_4 - 1))
                    {
                        _loc_5 = _loc_2[maxFrame];
                        if (_loc_5 != null)
                        {
                            for each (_loc_6 in _loc_5)
                            {
                                
                                Global.instance.callLater(_loc_6);
                            }
                        }
                        var _loc_9:* = _loc_3 + _loc_4;
                        _loc_3 = _loc_3 + _loc_4;
                    }
                    if (_loc_3 > 100)
                    {
                        _loc_3 = 100;
                    }
                    _loc_7 = 1;
                    while (_loc_7 <= _loc_3)
                    {
                        
                        _loc_8 = (this._lastFrame + _loc_7) % _loc_4;
                        _loc_5 = _loc_2[_loc_8];
                        if (_loc_5 != null)
                        {
                            for each (_loc_6 in _loc_5)
                            {
                                
                                Global.instance.callLater(_loc_6);
                            }
                        }
                        _loc_7++;
                    }
                }
                this.changeFrame = true;
            }
            else
            {
                this.changeFrame = false;
            }
            this._lastFrame = this._currentFrame;
            return;
        }// end function

        final public function get currentFrame() : int
        {
            return this._currentFrame;
        }// end function

        public function get isPlaying() : Boolean
        {
            return this._isPlaying;
        }// end function

        public function addFrameScript(param1:String, param2:int, param3:Function) : void
        {
            if (param2 > Modifier.maxFrame)
            {
                return;
            }
            var _loc_4:* = this.frameCallbackMap[param1];
            if (_loc_4 == null)
            {
                var _loc_6:* = new Dictionary(false);
                _loc_4 = new Dictionary(false);
                this.frameCallbackMap[param1] = _loc_6;
                _loc_4.len = 0;
            }
            var _loc_5:* = _loc_4[param2];
            if (_loc_5 == null)
            {
                var _loc_6:* = new Dictionary(false);
                _loc_5 = new Dictionary(false);
                _loc_4[param2] = _loc_6;
                var _loc_6:* = _loc_4;
                var _loc_7:* = _loc_4.len + 1;
                _loc_6.len = _loc_7;
            }
            if (!_loc_5[param3])
            {
                _loc_5[param3] = param3;
                var _loc_6:String = this;
                var _loc_7:* = this._scriptLen + 1;
                _loc_6._scriptLen = _loc_7;
            }
            return;
        }// end function

        public function removeFrameScript(param1:String, param2:int, param3:Function) : void
        {
            var _loc_5:Dictionary = null;
            var _loc_6:Boolean = false;
            var _loc_7:Function = null;
            var _loc_4:* = this.frameCallbackMap[param1];
            if (_loc_4 && _loc_4[param2] != null)
            {
                _loc_5 = _loc_4[param2];
                if (_loc_5[param3])
                {
                    var _loc_8:String = this;
                    var _loc_9:* = this._scriptLen - 1;
                    _loc_8._scriptLen = _loc_9;
                    delete _loc_5[param3];
                    _loc_6 = false;
                    for each (_loc_7 in _loc_5)
                    {
                        
                        _loc_6 = true;
                        break;
                    }
                    if (_loc_6)
                    {
                        delete _loc_4[param2];
                        var _loc_8:* = _loc_4;
                        var _loc_9:* = _loc_4.len - 1;
                        _loc_8.len = _loc_9;
                    }
                }
            }
            return;
        }// end function

        public function removeAllFrameScript() : void
        {
            this.frameCallbackMap = new Dictionary();
            this._scriptLen = 0;
            return;
        }// end function

        public function gotoAndPlay(param1:int, param2:String = null) : void
        {
            this._lastFrame = param1 - 1;
            if (param2 != null)
            {
                this.setPlayLable(param2);
            }
            this._targetObject3d.timerContorler.gotoFrame(param1, param1);
            this.currentFrame = param1;
            this.play();
            return;
        }// end function

        public function gotoAndStop(param1:int, param2:String = null) : void
        {
            this._lastFrame = param1 - 1;
            if (param2 != null)
            {
                this.setPlayLable(param2);
            }
            this._targetObject3d.timerContorler.gotoFrame(param1, param1);
            this.currentFrame = param1;
            this.stop();
            return;
        }// end function

        public function play() : void
        {
            this._isPlaying = true;
            return;
        }// end function

        public function stop() : void
        {
            this._isPlaying = false;
            return;
        }// end function

        protected function updateCurFrame() : void
        {
            var _loc_3:Boolean = false;
            if (!this._targetObject3d.timerContorler)
            {
                return;
            }
            var _loc_1:* = this._targetObject3d.timerContorler.curFrame - this.offsetFrame;
            var _loc_2:* = this.cuPlayLable.length;
            if (_loc_1 >= _loc_2)
            {
                if (this._targetObject3d.animationMode == PlayMode.ANIMATION_LOOP_MODE)
                {
                    _loc_1 = _loc_1 % _loc_2;
                }
                else
                {
                    _loc_1 = _loc_2 - 1;
                }
            }
            else if (_loc_1 < 0)
            {
                _loc_1 = 0;
            }
            this.currentFrame = this.cuPlayLable.from + _loc_1;
            return;
        }// end function

        public function changeBaseValue(param1:Object, param2:Number) : void
        {
            this._baseValue = param2;
            this._cache = new Array();
            return;
        }// end function

        public function updateBaseValue() : void
        {
            this._baseValue = this.getBaseValue(this.targetObject3d);
            this._cache = new Array();
            return;
        }// end function

        public function deleteKeyFrame(param1:Object, param2:int, param3:String) : void
        {
            var _loc_6:Label3D = null;
            var _loc_7:int = 0;
            var _loc_8:NodeAnimateKey = null;
            var _loc_4:* = getKeyFramePlaceByFrameIndex(param2, this._keyframes);
            if (_loc_4 == -1)
            {
                return;
            }
            var _loc_5:* = this._keyframes[_loc_4];
            if (_loc_5.frame == (this._keyframes.length - 1))
            {
                _loc_6 = param1 is String ? (this.getLabel(String(param1))) : (Label3D(param1));
                _loc_7 = _loc_4 - 1;
                _loc_7 = _loc_7 < 0 ? (0) : (_loc_7);
                _loc_8 = this._keyframes[_loc_7];
                _loc_6.change(_loc_6.from, _loc_8.frame);
            }
            this._keyframes.splice(_loc_4, 1);
            this._cache = new Array();
            return;
        }// end function

        public function offsetKeyFrame(param1:Object, param2:int, param3:int, param4:String) : void
        {
            var _loc_6:NodeAnimateKey = null;
            var _loc_9:int = 0;
            var _loc_5:* = this._keyframes.length;
            if (_loc_5 == 0)
            {
                return;
            }
            var _loc_7:* = param2;
            while (_loc_7 < _loc_5)
            {
                
                _loc_6 = this._keyframes[_loc_7];
                _loc_6.frame = _loc_6.frame + param3;
                _loc_7++;
            }
            if (param3 > 0 && param2 == 0)
            {
                this.editKeyFrame(param1, 0, param4, this._keyframes[0].value, this._keyframes[0].bezierVo);
            }
            else if (param3 < 0)
            {
                _loc_9 = -1;
                _loc_7 = 0;
                while (_loc_7 < _loc_5)
                {
                    
                    _loc_6 = this._keyframes[_loc_7];
                    if (_loc_6.frame > 0)
                    {
                        var _loc_10:int = 0;
                        this._keyframes[(_loc_7 - 1)].frame = 0;
                        _loc_9 = _loc_7 - 2;
                        break;
                    }
                    _loc_7++;
                }
                _loc_7 = 0;
                while (_loc_7 <= _loc_9)
                {
                    
                    this.deleteKeyFrame(param1, this._keyframes[_loc_7].frame, param4);
                    _loc_7++;
                }
            }
            var _loc_8:* = param1 is String ? (this.getLabel(String(param1))) : (Label3D(param1));
            _loc_8.change(_loc_8.from, _loc_8.to + param3);
            this._cache = new Array();
            return;
        }// end function

        public function get keyframes() : Array
        {
            return this._keyframes;
        }// end function

        public function parserKeyFrames(param1:Object) : void
        {
            var _loc_3:NodeAnimateKey = null;
            var _loc_5:Object = null;
            var _loc_6:Boolean = false;
            var _loc_7:BezierVo = null;
            var _loc_8:Object = null;
            var _loc_9:Number = NaN;
            this._keyframes.length = 0;
            var _loc_2:* = param1.length;
            var _loc_4:int = 0;
            while (_loc_4 < _loc_2)
            {
                
                _loc_5 = param1[_loc_4];
                _loc_6 = _loc_5.isLineTween == null ? (true) : (_loc_5.isLineTween);
                _loc_7 = new BezierVo(_loc_5.LX, _loc_5.LY, _loc_5.RX, _loc_5.RY, _loc_6);
                _loc_8 = _loc_5.attributes;
                if (_loc_8 is Array)
                {
                    _loc_9 = _loc_8[0].value;
                }
                else
                {
                    _loc_9 = Number(_loc_8);
                }
                var _loc_10:int = 0;
                _loc_9 = 0;
                _loc_3 = new NodeAnimateKey(_loc_5.index, _loc_9, _loc_7);
                this._keyframes.push(_loc_3);
                _loc_4++;
            }
            this._keyframes.sortOn("frame", Array.NUMERIC);
            this.setPlayLable(this.defaultLable);
            if (_loc_2 > 0)
            {
                this.defaultLable.change(0, this._keyframes[(_loc_2 - 1)].frame);
            }
            this.clearCache();
            return;
        }// end function

        public function clearCache() : void
        {
            this._cache.length = 0;
            return;
        }// end function

        public function editKeyFrame(param1:Object, param2:int, param3:String, param4, param5:BezierVo) : Object
        {
            var _loc_8:NodeAnimateKey = null;
            var _loc_6:* = param1 is String ? (this.getLabel(String(param1))) : (Label3D(param1));
            if (_loc_6.to < param2)
            {
                _loc_6.change(_loc_6.from, param2);
            }
            var _loc_7:* = getKeyFramePlaceByFrameIndex(param2, this._keyframes);
            if (_loc_7 == -1)
            {
                _loc_8 = new NodeAnimateKey(param2, param4, param5);
                this._keyframes.push(_loc_8);
                this._keyframes.sortOn("frame", Array.NUMERIC);
            }
            else
            {
                _loc_8 = this._keyframes[_loc_7];
                _loc_8.value = param4;
                _loc_8.bezierVo = param5;
            }
            this.clearCache();
            return _loc_8;
        }// end function

        public function get isDisposed() : Boolean
        {
            return this._isDisposed;
        }// end function

        public function set isDisposed(param1:Boolean) : void
        {
            this._isDisposed = param1;
            return;
        }// end function

        public function dispose(param1:Boolean = true) : void
        {
            if (this._isDisposed)
            {
                return;
            }
            this.stop();
            this.removeAllFrameScript();
            this.labels = new Dictionary(false);
            this.targetObject3d = null;
            FrEventDispatcher.instance.removeAllProxyEventListener(this);
            this._isPlaying = false;
            this._defaultLable = null;
            this._currentDuring = 0;
            this._lastFrame = -1;
            this.changeFrame = false;
            this.curPlayTrackName = null;
            this.cuPlayLable = null;
            this.autoPlay = true;
            this._currentFrame = 0;
            this._keyframes = new Array();
            this._cache = new Array();
            this.offsetFrame = 0;
            FrObjectPool.disposeObject(this);
            return;
        }// end function

        static function getKeyFramePlaceByFrameIndex(param1:int, param2:Array) : int
        {
            var _loc_5:INodeKey = null;
            var _loc_3:* = param2.length;
            var _loc_4:int = 0;
            while (_loc_4 < _loc_3)
            {
                
                _loc_5 = param2[_loc_4];
                if (_loc_5.frame == param1)
                {
                    return _loc_4;
                }
                _loc_4++;
            }
            return -1;
        }// end function

        static function getTimeIndex(param1:int, param2:Array) : int
        {
            var _loc_5:Object = null;
            var _loc_3:* = param2.length;
            var _loc_4:int = 1;
            while (_loc_4 < _loc_3)
            {
                
                _loc_5 = param2[_loc_4];
                if (_loc_5.frame > param1)
                {
                    return (_loc_4 - 1);
                }
                _loc_4++;
            }
            if (param1 <= param2[0].frame)
            {
                return 0;
            }
            if (param1 >= param2[(_loc_3 - 1)].frame)
            {
                return (_loc_3 - 1);
            }
            return -1;
        }// end function

    }
}
